﻿using System.IO;
using MIAP.Negocio;
using MIAP.Negocio.Utiles;

namespace MIAPWEB.Common
{
    public class CopyFiles
    {
        #region Campos

        /// <summary>
        /// Instancia unica de la clase.
        /// </summary>
        public static readonly CopyFiles Instance = new CopyFiles();

        #endregion

        #region variables

        /// <summary>
        /// Ruta especificada en el web.config
        /// </summary>
        private string _rutaArchivos;

        /// <summary>
        /// Ruta especificada de los apquetes el la tabla de configuracion
        /// </summary>
        private string _rutaPaquetes;

        /// <summary>
        /// Dominio de quien se hara la impersonalizacion
        /// </summary>
        private string _dominio;

        /// <summary>
        /// usuario por el cual nos autenticaremos
        /// </summary>
        private string _user;

        /// <summary>
        /// password del usuario
        /// </summary>
        private string _password;

        #endregion

        #region Constructores

        /// <summary>
        /// Constructor Privado. Evita la creacion de una instancia predeterminada de la clase <see cref="CopyFiles"/>
        /// </summary>        
        private CopyFiles()
        {
            this._rutaArchivos = new ConfiguracionNegocio().GetRutaArchivos().Descripcion;
            this._dominio = new ConfiguracionNegocio().GetNombreDominioImpersonate().Descripcion;
            this._user = new ConfiguracionNegocio().GetNombreUserImpersonate().Descripcion;
            this._password = new ConfiguracionNegocio().GetNombrePasswordImpersonate().Descripcion;
            this._rutaPaquetes = new ConfiguracionNegocio().GetRutaPaquetes().Descripcion;
        }

        #endregion

        /// <summary>
        /// Copia el archivo enviado en la carpeta de archivos del proyecto y cierra los streams correspondintes
        /// </summary>
        /// <param name="streamfile">stream del archivo a copiar</param>
        /// <param name="filename">nombre del archivo a copiar (con extension)</param>
        /// <param name="nombreProyecto">nombre del proyecto en el cual copiaremos los archivos</param>
        /// <param name="reemplaza"></param>
        public void CopyArchivo(Stream streamfile, string filename, bool reemplaza)
        {
            this.CopyFile(streamfile, filename, false, reemplaza);
        }

        /// <summary>
        /// Copia el contenido del stream a la ruta correspondiente, y cierra los streams correspondintes
        /// </summary>
        /// <param name="streamfile">stream del archivo a copiar</param>
        /// <param name="filename">nombre del archivo a copiar (con extension)</param>
        /// <param name="nombreProyecto">nombre del proyecto en el cual copiaremos los archivos</param>
        /// <param name="isPackage">true si se copiara en la carpeta de paquetes, false si se compiara en la de archivos</param>
        /// <param name="reemplaza"></param>
        private void CopyFile(Stream streamfile, string filename, bool isPackage, bool reemplaza = false)
        {
#if !DEBUG
            using (new Impersonation(this._dominio, this._user, this._password))
            {
#endif
            var ruta = isPackage?this._rutaPaquetes:this._rutaArchivos;
            this.CreateFolder(ruta);
            ruta = Path.Combine(ruta, filename);
            if (reemplaza && File.Exists(ruta))
            {
                File.Delete(ruta);
            }
            using (Stream file = File.OpenWrite(ruta))
            {
                CopyStream(streamfile, file);
            }
            streamfile.Close();
#if !DEBUG
            }
#endif
        }

        /// <summary>
        /// Copia el contenido de un stream a otro, no ciera ningun stream
        /// </summary>
        private static void CopyStream(Stream input, Stream output)
        {
            var buffer = new byte[8 * 1024];
            int len;
            while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, len);
            }
        }

        /// <summary>
        /// Revisa si existe la ruta especificada y si no la crea
        /// </summary>
        /// <param name="folder"></param>
        private void CreateFolder(string folder)
        {
            if (!Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }
        }

        /// <summary>
        /// Obtiene la ruta especificada donde se encuentran los archivos
        /// </summary>
        /// <returns></returns>
        public string GetRutaArchivos()
        {
            return this._rutaArchivos;
        }

        /// <summary>
        /// Obtiene la ruta especificada donde se encuentran los paquetes
        /// </summary>
        /// <returns></returns>
        public string GetRutaPaquetes()
        {
            return this._rutaPaquetes;
        }
    }
}